<?php

declare(strict_types=1);

namespace wym\taglib\layui;

use wym\taglib\Taglib;

class Form extends Taglib
{
    /**
     * 定义标签前缀
     */
    protected string $tag = 'form:';

    /**
     * 定义标签对应样式
     */
    protected array $class = [
        'form' => ['form', 'layui-form'],

        'button' => ['button', 'layui-btn'],
        'submit' => ['button', 'layui-btn'],
        'reset'  => ['button', 'layui-btn'],

        'text'     => ['input', 'layui-input'],
        'password' => ['input', 'layui-input'],
        'hidden'   => ['input', ''],
        'number'   => ['input', 'layui-input'],
        'checkbox' => ['input', ''],
        'switch'   => ['input', ''],
        'radio'    => ['input', ''],

        'textarea' => ['textarea', 'layui-textarea'],
        'select'   => ['select', ''],

        'label'    => ['label', 'layui-form-label'],
        'a'        => ['a', ''],
        'fieldset' => ['fieldset', 'layui-elem-field'],
        'icon'     => ['i', 'layui-icon'],
        'table'    => ['table', 'layui-table'],

        'item'   => ['div', 'layui-form-item'],
        'wrap'   => ['div', 'layui-input-wrap'],
        'group'  => ['div', 'layui-input-group'],
        'prefix' => ['div', 'layui-input-prefix'],
        'suffix' => ['div', 'layui-input-suffix'],
        'inline' => ['div', 'layui-input-inline'],
        'block'  => ['div', 'layui-input-block'],
        'mid'    => ['div', 'layui-form-mid'],
    ];

    /**
     * 定义标签列表
     */
    protected $tags = [
        // 标签定义： attr 属性列表 close 是否闭合（0 或者1 默认1） alias 标签别名 level 嵌套层次
        'form'     => ['attr' => ''],
        'button'   => ['attr' => '', 'close' => 0, 'alias' => ['submit,reset', 'label']],
        'input'    => ['attr' => '', 'close' => 0, 'alias' => ['text,password,hidden,number', 'label']],
        'checkbox' => ['attr' => '', 'close' => 0, 'alias' => ['none,tag,switch', 'label']],
        'radio'    => ['attr' => 'list', 'close' => 0],

        'textarea' => ['attr' => ''],
        'select'   => ['attr' => ''],

        'div'      => ['attr' => ''],
        'item'     => ['attr' => ''],
        'wrap'     => ['attr' => ''],
        'group'    => ['attr' => ''],
        'prefix'   => ['attr' => ''],
        'suffix'   => ['attr' => ''],
        'inline'   => ['attr' => ''],
        'block'    => ['attr' => ''],
        'label'    => ['attr' => '', 'close' => 0],
        'a'        => ['attr' => '', 'close' => 0],
        'fieldset' => ['attr' => ''],
        'icon'     => ['attr' => 'class', 'close' => 0],
        'mid'      => ['attr' => '', 'close' => 0],
        'table'    => ['attr' => '', 'close' => 0],
    ];

    protected array $attr = ['id', 'style', 'lay-event'];

    /**
     * form标签解析
     * 格式：{form:form}{/form:form}
     *
     * @access public
     *
     * @param array  $tag     标签
     * @param string $content 标签内容
     *
     * @return string
     */
    public function tagForm(array $tag, string $content): string
    {
        $tag['label'] = 'form';

        return $this->element(
            $tag,
            $content,
            static::getUrl($tag, 'action') . static::getAttr($tag, ['method', 'lay-filter', 'autocomplete', 'name'])
        );
    }

    /**
     * 这是一个Layui样式的标签
     *
     * @param array       $tag     标签
     * @param mixed       $content 标签内容
     * @param string|null $extend
     *
     * @return string
     */
    private function element(array $tag, ?string $content = null, ?string $extend = null): string
    {
        [$label, $class] = static::getClass($tag);

        return '<' . $label . $class . static::getAttr(
                $tag,
                $this->attr
            ) . $extend . '>' . ($content ? $content . '</' . $label . '>' : '');
        //        return '<' . $label . static::getId($tag) . static::getName($tag) . $class . static::getLayFilter($tag) . static::getStyle($tag) . static::getLayEvent($tag) . static::getUrl($tag) . static::getTitle($tag) . static::getValue($tag) . static::getHref($tag) . static::getLayAffix($tag) . static::getPlaceholder($tag) . static::getLayVerify($tag) . static::getLaySearch($tag) . static::getStep($tag) . static::getMin($tag) . static::getMax($tag) . static::getAutocomplete($tag) . static::getDisabled($tag) . $extend . '>' . $content . '</' . $label . '>';
    }

    /**
     * button标签解析
     * 格式：{form:button /}|{form:submit /}|{form:reset /}
     *
     * @access public
     *
     * @param array $tag 标签
     *
     * @return string
     */
    public function tagButton(array $tag): string
    {
        $tag['label'] = $tag['label'] ?? 'button';
        switch ($tag['label']) {
            case 'submit':
                $tag['lay-filter'] = $tag['lay-filter'] ?? 'ok';
                $extend            = static::getAttr($tag, ['name', 'lay-filter']) . ' lay-submit';
                break;
            case 'reset':
                $extend = static::getType($tag);
                break;
            default:
                $extend = static::getUrl($tag) . static::getAttr($tag, 'lay-filter');
                break;
        }
        if (isset($tag['icon'])) {
            $icon = static::tagIcon(['class' => $tag['icon']]);
        } else {
            $icon = '';
        }

        return $this->element($tag, $icon . static::getLang($tag), static::getTitle($tag) . $extend);
    }

    /**
     * icon标签解析
     * 格式：{form:icon/}
     *
     * @access public
     *
     * @param array $tag 标签
     *
     * @return string
     */
    public function tagIcon(array $tag): string
    {
        $tag['label'] = 'icon';

        return $this->element($tag) . '</i>';
    }

    /**
     * input标签解析
     * 格式：{form:text /}
     *
     * @access public
     *
     * @param array $tag 标签
     *
     * @return string
     */
    public function tagInput(array $tag): string
    {
        $extend = '';

        switch ($tag['label']) {
            case 'text':
                $tag['lay-affix'] = $tag['lay-affix'] ?? 'clear';
                $extend           = static::getPlaceholder($tag) . static::getLayVerify($tag) . static::getAutocomplete(
                        $tag
                    );
                break;
            case 'password':
                $tag['lay-affix'] = $tag['lay-affix'] ?? 'eye';
                $extend           = static::getPlaceholder($tag) . static::getLayVerify($tag) . static::getAutocomplete(
                        $tag
                    );
                break;
            case 'number':
                $tag['lay-affix'] = $tag['lay-affix'] ?? 'number';
                $extend           = static::getAttr($tag, ['step', 'min', 'max']) . static::getAutocomplete($tag);
                break;
        }

        return $this->element(
            $tag,
            null,
            static::getValue($tag) . static::getAttr($tag, ['name', 'lay-affix', "disabled", "lay-filter"]
            ) . static::getType(
                $tag
            ) . $extend
        );
    }

    /**
     * checkbox标签解析
     * 格式：{form:checkbox /}
     *
     * @access public
     *
     * @param array $tag 标签
     *
     * @return string
     */
    public function tagCheckbox(array $tag): string
    {
        $extend = empty($tag['label']) ? '' : ' lay-skin="' . $tag['label'] . '"';
        switch ($tag['label']) {
            case 'tag':
                $extend .= ' title="normal"';
                break;
            case 'switch':
                $extend .= ' title="{:\\\wym\\\taglib\\\TagLib::lang(\'normal\')}|{:\\\wym\\\taglib\\\TagLib::lang(\'locked\')}" ' . static::getAttr(
                        $tag,
                        ['name']
                    );
                break;
            case 'none':
                $extend .= '';
                break;
        }

        $tag['label'] = 'checkbox';

        return $this->element($tag, null, static::getType($tag) . $extend);
    }

    /**
     * radio标签解析
     * 格式：{form:radio /}
     *
     * @access public
     *
     * @param array $tag 标签
     *
     * @return string
     */
    public function tagRadio(array $tag): string
    {
        $tag['label'] = 'radio';
        $value        = $tag['value'] ?? 'rs';

        if (empty($value)) {
            return '';
        }
        $name  = empty($tag['name']) ? '' : $tag['name'];
        $parse = '<?php ';
        $parse .= '$__LIST__ =$' . $tag['list'] . ';';
        $parse .= ' ?>';
        $parse .= '{volist name="__LIST__" id="__TAG__"}';
        $parse .= '<input' . static::getType($tag) . static::getAttr($tag, ['name', 'lay-filter']);
        $parse .= ' title="{$__TAG__.title|default=$key}" value="{$key}"';

        if (isset($tag['checked'])) {
            if (empty($name)) {
                $parse .= '{present name="' . $value . '"}{eq name="' . $value . '" value="$key"} checked{/eq}{/present}';
            } else {
                $parse .= '{present name="' . $value . '[\'' . $name . '\']"}{eq name="' . $value . '[\'' . $name . '\']" value="$key"} checked{/eq}{/present}';
            }
        }
        $parse .= static::getLayVerify($tag) . '>';
        $parse .= '{/volist}';

        return $parse;
    }

    /**
     * textarea标签解析
     * 格式：{form:textarea}{/form:textarea}
     *
     * @access public
     *
     * @param array  $tag     标签
     * @param string $content 标签内容
     *
     * @return string
     */
    public function tagTextarea(array $tag, string $content): string
    {
        $tag['label'] = 'textarea';

        return $this->element(
                $tag,
                static::getLang($tag) . $content,
                static::getPlaceholder($tag) . static::getLayVerify($tag) . static::getAttr($tag, 'name')
            ) . (empty($content) ? '</textarea>' : '');
    }

    /**
     * select标签解析
     * 格式：{form:select}{/form:select}
     *
     * @access public
     *
     * @param array  $tag     标签
     * @param string $content 标签内容
     *
     * @return string
     */
    public function tagSelect(array $tag, string $content): string
    {
        $tag['label'] = 'select';

        return $this->element(
                $tag,
                static::getLang($tag) . $content,
                static::getAttr($tag, ['name', 'lay-append-to']) . static::getLayVerify($tag)
            ) . (empty($content) ? '</select>' : '');
    }

    /**
     * div标签解析
     * 格式：{form:div}{/form:div}
     *
     * @access public
     *
     * @param array  $tag     标签
     * @param string $content 标签内容
     *
     * @return string
     */
    public function tagDiv(array $tag, string $content): string
    {
        $tag['label'] = 'div';

        return $this->element($tag, $content);
    }

    /**
     * item标签解析
     * 格式：{form:item}{/form:item}
     *
     * @access public
     *
     * @param array  $tag     标签
     * @param string $content 标签内容
     *
     * @return string
     */
    public function tagItem(array $tag, string $content): string
    {
        $tag['label'] = 'item';

        return $this->element($tag, $content);
    }

    /**
     * wrap标签解析
     * 格式：{form:wrap}{/form:wrap}
     *
     * @access public
     *
     * @param array  $tag     标签
     * @param string $content 标签内容
     *
     * @return string
     */
    public function tagWrap(array $tag, string $content): string
    {
        $tag['label'] = 'wrap';

        return $this->element($tag, $content);
    }

    /**
     * group标签解析
     * 格式：{form:group}{/form:group}
     *
     * @access public
     *
     * @param array  $tag     标签
     * @param string $content 标签内容
     *
     * @return string
     */
    public function tagGroup(array $tag, string $content): string
    {
        $tag['label'] = 'group';

        return $this->element($tag, $content);
    }

    /**
     * prefix标签解析
     * 格式：{form:prefix}{/form:prefix}
     *
     * @access public
     *
     * @param array  $tag     标签
     * @param string $content 标签内容
     *
     * @return string
     */
    public function tagPrefix(array $tag, string $content): string
    {
        $tag['label'] = 'prefix';

        return $this->element($tag, $content);
    }

    /**
     * suffix
     * 格式：{form:suffix}{/form:suffix}
     *
     * @access public
     *
     * @param array  $tag     标签
     * @param string $content 标签内容
     *
     * @return string
     */
    public function tagSuffix(array $tag, string $content): string
    {
        $tag['label'] = 'suffix';

        return $this->element($tag, $content);
    }

    /**
     * inline标签解析
     * 格式：{form:inline}{/form:inline}
     *
     * @access public
     *
     * @param array  $tag     标签
     * @param string $content 标签内容
     *
     * @return string
     */
    public function tagInline(array $tag, string $content): string
    {
        $tag['label'] = 'inline';

        return $this->element($tag, $content);
    }

    /**
     * block标签解析
     * 格式：{form:block}{/form:block}
     *
     * @access public
     *
     * @param array  $tag     标签
     * @param string $content 标签内容
     *
     * @return string
     */
    public function tagBlock(array $tag, string $content): string
    {
        $tag['label'] = 'block';

        return $this->element($tag, $content);
    }

    /**
     * label标签解析
     * 格式：{form:label/}
     *
     * @access public
     *
     * @param array $tag 标签
     *
     * @return string
     */
    public function tagLabel(array $tag): string
    {
        $tag['label'] = 'label';

        return $this->element($tag, static::getLang($tag));
    }

    /**
     * mid标签解析
     * 格式：{form:mid/}
     *
     * @access public
     *
     * @param array $tag 标签
     *
     * @return string
     */
    public function tagMid(array $tag): string
    {
        $tag['label'] = 'mid';

        return $this->element($tag, static::getLang($tag));
    }

    /**
     * a标签解析
     * 格式：{form:a}{/form:a}
     *
     * @access public
     *
     * @param array $tag 标签
     *
     * @return string
     */
    public function tagA(array $tag): string
    {
        $tag['label'] = 'a';

        return $this->element($tag, static::getLang($tag), static::getAttr($tag, 'lay-filter') . static::getHref($tag));
    }

    /**
     * fieldset标签解析
     * 格式：{form:fieldset}{/form:fieldset}
     *
     * @access public
     *
     * @param array  $tag     标签
     * @param string $content 标签内容
     *
     * @return string
     */
    public function tagFieldset(array $tag, string $content): string
    {
        $tag['label'] = 'fieldset';

        return $this->element($tag, static::getLang($tag) . $content);
    }

    /**
     * table标签解析
     * 格式：{form:table/}
     *
     * @access public
     *
     * @param array $tag 标签
     *
     * @return string
     */
    public function tagTable(array $tag): string
    {
        $tag['label']      = 'table';
        $tag['lay-filter'] = $tag['lay-filter'] ?? (empty($tag['id']) ? '' : trim($tag['id']));

        return $this->element($tag) . '</' . $tag['label'] . '>';
    }
}
